package ducna.misscall.screen.contact;

/**
 * @author DUCNA
 */
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;

import android.app.SearchManager;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Contacts.Photo;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import ducna.alozo.misscall.R;
import ducna.misscall.comon.fragment.BaseFragment;
import ducna.misscall.screen.contact.adapter.ContactAdapter;
import ducna.misscall.screen.contact.image.ImageLoader;
import ducna.misscall.screen.contact.model.ContactsQuery;
import ducna.misscall.utils.Logger;
import ducna.misscall.utils.Utils;

public class ContactFragment extends BaseFragment implements
		LoaderCallbacks<Cursor>, ContactsQuery {
	public static final String TAG = ContactFragment.class.getSimpleName();

	// Bundle key for saving previously selected search result item
	private static final String STATE_PREVIOUSLY_SELECTED_KEY = "ducna.misscall.screen.contact.SELECTED_ITEM";

	private ContactAdapter mAdapter; // The main query adapter
	private ImageLoader mImageLoader; // Handles loading the contact image in a
										// background thread
	private String mSearchTerm; // Stores the current search query term

	// Contact selected listener that allows the activity holding this fragment
	// to be notified of
	// a contact being selected
	private OnContactsInteractionListener mOnContactSelectedListener;

	// Stores the previously selected search item so that on a configuration
	// change the same item
	// can be reselected again
	private int mPreviouslySelectedSearchItem = 0;

	// Whether or not the search query has changed since the last time the
	// loader was refreshed
	private boolean mSearchQueryChanged;

	// Whether or not this is a search result view of this fragment, only used
	// on pre-honeycomb
	// OS versions as search results are shown in-line via Action Bar search
	// from honeycomb onward
	private boolean mIsSearchResultView = false;

	private ListView mListViewContact;
	@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		/*
         * An ImageLoader object loads and resizes an image in the background and binds it to the
         * QuickContactBadge in each item layout of the ListView. ImageLoader implements memory
         * caching for each image, which substantially improves refreshes of the ListView as the
         * user scrolls through it.
         *
         * To learn more about downloading images asynchronously and caching the results, read the
         * Android training class Displaying Bitmaps Efficiently.
         *
         * http://developer.android.com/training/displaying-bitmaps/
         */
        mImageLoader = new ImageLoader(getActivity(), getListPreferredItemHeight()) {
            @Override
            protected Bitmap processBitmap(Object data) {
                // This gets called in a background thread and passed the data from
                // ImageLoader.loadImage().
                return loadContactPhotoThumbnail((String) data, getImageSize());
            }
        };

        // Set a placeholder loading image for the image loader
        mImageLoader.setLoadingImage(R.drawable.ic_contact_picture_holo_light);

        // Add a cache to the image loader
        mImageLoader.addImageCache(getActivity().getSupportFragmentManager(), 0.1f);
        
        mAdapter = new ContactAdapter(getActivity(), mImageLoader);
	}
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.fragment_contact, container,
				false);
		mListViewContact = (ListView) view.findViewById(R.id.listViewContact);
		return view;
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onActivityCreated(savedInstanceState);
		
		mListViewContact.setAdapter(mAdapter);
		
		 if (mPreviouslySelectedSearchItem == 0) {
			 Logger.out(TAG, "mPreviouslySelectedSearchItem11111111111111111111");
	            // Initialize the loader, and create a loader identified by ContactsQuery.QUERY_ID
	            getLoaderManager().initLoader(ContactsQuery.QUERY_ID, null, this);
	        }
	}
	@Override
	public void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		if (!TextUtils.isEmpty(mSearchTerm)) {
			// Saves the current search string
			outState.putString(SearchManager.QUERY, mSearchTerm);

			// Saves the currently selected contact
			outState.putInt(STATE_PREVIOUSLY_SELECTED_KEY,
					mListViewContact.getCheckedItemPosition());
		}
	}

	@Override
	public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
		if (id == QUERY_ID) {
			Uri contentUri;
			if (mSearchTerm == null) {
				// Since there's no search string, use the content URI that
				// searches the entire
				// Contacts table
				contentUri = CONTENT_URI;
			} else {
				// Since there's a search string, use the special content Uri
				// that searches the
				// Contacts table. The URI consists of a base Uri and the search
				// string.
				contentUri = Uri.withAppendedPath(FILTER_URI,
						Uri.encode(mSearchTerm));
				return new CursorLoader(getActivity(), contentUri, PROJECTION,
						SELECTION, null, SORT_ORDER);
			}
		}
		
        Logger.out(TAG, "onCreateLoader - incorrect ID provided (" + id + ")");

		return null;
	}

	@Override
	public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
		if (loader.getId() == QUERY_ID) {
			mAdapter.swapCursor(cursor);
	        Logger.out(TAG, "onLoadFinished 1== " +  mAdapter.getCount());
		}else {
	        Logger.out(TAG, "onLoadFinished 2== " +  mAdapter.getCount());

		}
	}

	@Override
	public void onLoaderReset(Loader<Cursor> loader) {
		if (loader.getId() == QUERY_ID) {
			// When the loader is being reset, clear the cursor from the
			// adapter. This allows the
			// cursor resources to be freed.
			mAdapter.swapCursor(null);
		}
	}

	/**
	 * This interface must be implemented by any activity that loads this
	 * fragment. When an interaction occurs, such as touching an item from the
	 * ListView, these callbacks will be invoked to communicate the event back
	 * to the activity.
	 */
	public interface OnContactsInteractionListener {
		/**
		 * Called when a contact is selected from the ListView.
		 * 
		 * @param contactUri
		 *            The contact Uri.
		 */
		public void onContactSelected(Uri contactUri);

		/**
		 * Called when the ListView selection is cleared like when a contact
		 * search is taking place or is finishing.
		 */
		public void onSelectionCleared();
	}

	/**
	 * In platform versions prior to Android 3.0, the ActionBar and SearchView
	 * are not supported, and the UI gets the search string from an EditText.
	 * However, the fragment doesn't allow another search when search results
	 * are already showing. This would confuse the user, because the resulting
	 * search would re-query the Contacts Provider instead of searching the
	 * listed results. This method sets the search query and also a boolean that
	 * tracks if this Fragment should be displayed as a search result view or
	 * not.
	 *
	 * @param query
	 *            The contacts search query.
	 */
	public void setSearchQuery(String query) {
		if (TextUtils.isEmpty(query)) {
			mIsSearchResultView = false;
		} else {
			mSearchTerm = query;
			mIsSearchResultView = true;
		}
	}

	/**
	 * Gets the preferred height for each item in the ListView, in pixels, after
	 * accounting for screen density. ImageLoader uses this value to resize
	 * thumbnail images to match the ListView item height.
	 *
	 * @return The preferred height in pixels, based on the current theme.
	 */
	private int getListPreferredItemHeight() {
		final TypedValue typedValue = new TypedValue();

		// Resolve list item preferred height theme attribute into typedValue
		getActivity().getTheme().resolveAttribute(
				android.R.attr.listPreferredItemHeight, typedValue, true);

		// Create a new DisplayMetrics object
		final DisplayMetrics metrics = new android.util.DisplayMetrics();

		// Populate the DisplayMetrics
		getActivity().getWindowManager().getDefaultDisplay()
				.getMetrics(metrics);

		// Return theme value based on DisplayMetrics
		return (int) typedValue.getDimension(metrics);
	}

	/**
	 * Decodes and scales a contact's image from a file pointed to by a Uri in
	 * the contact's data, and returns the result as a Bitmap. The column that
	 * contains the Uri varies according to the platform version.
	 *
	 * @param photoData
	 *            For platforms prior to Android 3.0, provide the Contact._ID
	 *            column value. For Android 3.0 and later, provide the
	 *            Contact.PHOTO_THUMBNAIL_URI value.
	 * @param imageSize
	 *            The desired target width and height of the output image in
	 *            pixels.
	 * @return A Bitmap containing the contact's image, resized to fit the
	 *         provided image size. If no thumbnail exists, returns null.
	 */
	private Bitmap loadContactPhotoThumbnail(String photoData, int imageSize) {

		// Ensures the Fragment is still added to an activity. As this method is
		// called in a
		// background thread, there's the possibility the Fragment is no longer
		// attached and
		// added to an activity. If so, no need to spend resources loading the
		// contact photo.
		if (!isAdded() || getActivity() == null) {
			return null;
		}

		// Instantiates an AssetFileDescriptor. Given a content Uri pointing to
		// an image file, the
		// ContentResolver can return an AssetFileDescriptor for the file.
		AssetFileDescriptor afd = null;

		// This "try" block catches an Exception if the file descriptor returned
		// from the Contacts
		// Provider doesn't point to an existing file.
		try {
			Uri thumbUri;
			// If Android 3.0 or later, converts the Uri passed as a string to a
			// Uri object.
			if (Utils.hasHoneycomb()) {
				thumbUri = Uri.parse(photoData);
			} else {
				// For versions prior to Android 3.0, appends the string
				// argument to the content
				// Uri for the Contacts table.
				final Uri contactUri = Uri.withAppendedPath(
						Contacts.CONTENT_URI, photoData);

				// Appends the content Uri for the Contacts.Photo table to the
				// previously
				// constructed contact Uri to yield a content URI for the
				// thumbnail image
				thumbUri = Uri.withAppendedPath(contactUri,
						Photo.CONTENT_DIRECTORY);
			}
			// Retrieves a file descriptor from the Contacts Provider. To learn
			// more about this
			// feature, read the reference documentation for
			// ContentResolver#openAssetFileDescriptor.
			afd = getActivity().getContentResolver().openAssetFileDescriptor(
					thumbUri, "r");

			// Gets a FileDescriptor from the AssetFileDescriptor. A
			// BitmapFactory object can
			// decode the contents of a file pointed to by a FileDescriptor into
			// a Bitmap.
			FileDescriptor fileDescriptor = afd.getFileDescriptor();

			if (fileDescriptor != null) {
				// Decodes a Bitmap from the image pointed to by the
				// FileDescriptor, and scales it
				// to the specified width and height
				return ImageLoader.decodeSampledBitmapFromDescriptor(
						fileDescriptor, imageSize, imageSize);
			}
		} catch (FileNotFoundException e) {
			// If the file pointed to by the thumbnail URI doesn't exist, or the
			// file can't be
			// opened in "read" mode, ContentResolver.openAssetFileDescriptor
			// throws a
			// FileNotFoundException.
			Logger.d(TAG, "Contact photo thumbnail not found for contact "
					+ photoData + ": " + e.toString());
		} finally {
			// If an AssetFileDescriptor was returned, try to close it
			if (afd != null) {
				try {
					afd.close();
				} catch (IOException e) {
					// Closing a file descriptor might cause an IOException if
					// the file is
					// already closed. Nothing extra is needed to handle this.
				}
			}
		}

		// If the decoding failed, returns null
		return null;
	}
}
